{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import multiprocessing\n",
    "import numpy as np\n",
    "from deap import creator, base, tools, algorithms\n",
    "from vnpy.app.cta_strategy.backtesting import BacktestingEngine,OptimizationSetting\n",
    "from vnpy.app.cta_strategy.strategies.boll_channel_strategy import BollChannelStrategy\n",
    "from vnpy.app.cta_strategy.strategies.atr_rsi_strategy import AtrRsiStrategy\n",
    "from datetime import datetime\n",
    "import multiprocessing           #多进程\n",
    "from functools import lru_cache"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "setting = OptimizationSetting()\n",
    "#setting.add_parameter('atr_length', 10, 50, 2)\n",
    "#setting.add_parameter('atr_ma_length', 10, 50, 2)\n",
    "#setting.add_parameter('rsi_length', 4, 50, 2)\n",
    "#setting.add_parameter('rsi_entry', 4, 30, 1)\n",
    "setting.add_parameter('boll_window', 4, 50, 2)\n",
    "#setting.add_parameter('boll_dev', 4, 50, 2)\n",
    "setting.add_parameter('cci_window', 4, 50, 2)\n",
    "setting.add_parameter('atr_window', 4, 50, 2)\n",
    "\n",
    "\n",
    "local_setting = setting.generate_setting()\n",
    "total_sample = len(local_setting)\n",
    "print(\"数据总体：\",total_sample)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "setting_names = random.choice(local_setting).keys()\n",
    "setting_names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parameter_generate():\n",
    "    setting_param = list(random.choice(local_setting).values())\n",
    "    return setting_param"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "parameter_generate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "setting=dict(zip(setting_names,parameter_generate()))\n",
    "setting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def object_func(strategy_avg):\n",
    "    \"\"\"\"\"\"\n",
    "    return run_backtesting(tuple(strategy_avg))\n",
    "    #return run_backtesting(strategy_avg)\n",
    "    \n",
    "\n",
    "@lru_cache(maxsize=1000000)\n",
    "def run_backtesting(strategy_avg):\n",
    "    # 创建回测引擎对象\n",
    "    engine = BacktestingEngine()\n",
    "    engine.set_parameters(\n",
    "        vt_symbol=\"IF88.CFFEX\",\n",
    "        interval=\"1m\",\n",
    "        start=datetime(2016, 1, 1),\n",
    "        end=datetime(2019, 1,1),\n",
    "        rate=0.3/10000,\n",
    "        slippage=0.2,\n",
    "        size=300,\n",
    "        pricetick=0.2,\n",
    "        capital=1_000_000,\n",
    "    )\n",
    "    \n",
    "    setting=dict(zip(setting_names,strategy_avg))\n",
    "           \n",
    "\n",
    "    #加载策略          \n",
    "    #engine.initStrategy(TurtleTradingStrategy, setting)\n",
    "    engine.add_strategy(BollChannelStrategy, setting)\n",
    "    engine.load_data()\n",
    "    engine.run_backtesting()\n",
    "    engine.calculate_result()\n",
    "    result = engine.calculate_statistics(output=False)\n",
    "\n",
    "    return_drawdown_ratio = round(result['return_drawdown_ratio'],2)  #收益回撤比\n",
    "    sharpe_ratio= round(result['sharpe_ratio'],2)                   #夏普比率\n",
    "    return return_drawdown_ratio , sharpe_ratio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "object_func(parameter_generate())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target_names = [\"return_drawdown_ratio\" , \"sharpe_ratio\"]\n",
    "def show_result(hof):\n",
    "    for i in range(len(hof)):\n",
    "        solution = hof[i]    \n",
    "        parameter=dict(zip(setting_names,solution))\n",
    "        result=dict(zip(target_names,list(object_func(solution))))\n",
    "        print({**parameter, **result})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from time import time\n",
    "#设置优化方向：最大化收益回撤比，最大化夏普比率\n",
    "creator.create(\"FitnessMax\", base.Fitness, weights=(1.0, 1.0)) # 1.0 求最大值；-1.0 求最小值\n",
    "creator.create(\"Individual\", list, fitness=creator.FitnessMax)\n",
    "\n",
    "def optimize(population=None):\n",
    "    \"\"\"\"\"\"           \n",
    "    start = time()    \n",
    "    toolbox = base.Toolbox() \n",
    "\n",
    "    # 初始化     \n",
    "    toolbox.register(\"individual\", tools.initIterate, creator.Individual,parameter_generate)                          \n",
    "    toolbox.register(\"population\", tools.initRepeat, list, toolbox.individual)                                            \n",
    "    toolbox.register(\"mate\", tools.cxTwoPoint)                                               \n",
    "    toolbox.register(\"mutate\", tools.mutUniformInt,low = 4,up = 40,indpb=1)               \n",
    "    toolbox.register(\"evaluate\", object_func)                                                \n",
    "    toolbox.register(\"select\", tools.selNSGA2)       \n",
    "    pool = multiprocessing.Pool(multiprocessing.cpu_count())\n",
    "    toolbox.register(\"map\", pool.map)\n",
    "    #toolbox.register(\"map\", futures.map)\n",
    "    \n",
    "    \n",
    "    #遗传算法参数设置\n",
    "    MU = 80                                  #设置每一代选择的个体数\n",
    "    LAMBDA = 100  #设置每一代产生的子女数\n",
    "    POP=100\n",
    "    CXPB, MUTPB, NGEN = 0.95, 0.05,30        #分别为种群内部个体的交叉概率、变异概率、产生种群代数\n",
    "    \n",
    "    if population==None:\n",
    "        LAMBDA = POP = int(pow(total_sample, 1/2.7))\n",
    "        MU = int(0.8*POP)    \n",
    "    \n",
    "    pop = toolbox.population(POP)            #设置族群里面的个体数量\n",
    "    hof = tools.ParetoFront()                #解的集合：帕累托前沿(非占优最优集)\n",
    "\n",
    "    stats = tools.Statistics(lambda ind: ind.fitness.values)\n",
    "    np.set_printoptions(suppress=True)            #对numpy默认输出的科学计数法转换\n",
    "    stats.register(\"mean\", np.mean, axis=0)       #统计目标优化函数结果的平均值\n",
    "    stats.register(\"std\", np.std, axis=0)         #统计目标优化函数结果的标准差\n",
    "    stats.register(\"min\", np.min, axis=0)         #统计目标优化函数结果的最小值\n",
    "    stats.register(\"max\", np.max, axis=0)         #统计目标优化函数结果的最大值\n",
    "    print(\"开始运行遗传算法，每代族群总数：%s, 优良品种筛选个数：%s，迭代次数：%s，交叉概率：%s，突变概率：%s\" %(POP,MU,NGEN,CXPB,MUTPB))\n",
    "    \n",
    "\n",
    "    #运行算法\n",
    "    algorithms.eaMuPlusLambda(pop, toolbox, MU, LAMBDA, CXPB, MUTPB, NGEN, stats,\n",
    "                              halloffame=hof)     #esMuPlusLambda是一种基于(μ+λ)选择策略的多目标优化分段遗传算法\n",
    "\n",
    "    end = time()\n",
    "    cost = int((end - start))\n",
    "\n",
    "    print(\"遗传算法优化完成，耗时%s秒\"% (cost))\n",
    "    print(\"输出帕累托前沿解集：\")\n",
    "    show_result(hof)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "optimize()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    MU = 80                                  #设置每一代选择的个体数\n",
    "    POP = 100                             #设置每一代产生的子女数\n",
    "    CXPB, MUTPB, NGEN = 0.95, 0.05,20 \n",
    "    print(\"开始运行遗传算法，每代族群总数：%s, 优良品种筛选个数：%s，迭代次数：%s，交叉概率：%s，突变概率：%s\" %(POP,MU,NGEN,CXPB,MUTPB))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
